/**
  @Author: 王炜皓
  @Date: 2023-05-22 15:00:59
  @LastEditTime: 2023-05-29 13:55:39
  @LastEditors: 王炜皓
  @Description: 坐标转换主类
  @FilePath: \utum-cesium\src\views\test\extend\CoodTransform.js
 **/
/**
 * 天地图 CGCS2000(EPSG:4490)
 * 经纬度 wgs84（EPSG:4326）
 * 高德百度 火星坐标系
 * 
 */
  
  const BD_FACTOR = (3.14159265358979324 * 3000.0) / 180.0;
  const PI = 3.1415926535897932384626;
  const RADIUS = 6378245.0;
  const EE = 0.00669342162296594323;
  const Cesium = window.Cesium;
  class CoordTransform {
    /**
     * 笛卡尔坐标转WGS84
     * @param {object} cartesian 笛卡尔坐标
     * @returns {object} {lng,lat,alt} WGS84经纬度坐标
     */
    static Cartesian3ToWGS84(cartesian) {
      let ellipsoid = Cesium.Ellipsoid.WGS84;
      let cartographic = ellipsoid.cartesianToCartographic(cartesian);
      return {
        lng: Cesium.Math.toDegrees(cartographic.longitude),
        lat: Cesium.Math.toDegrees(cartographic.latitude),
        alt: cartographic.height,
      };
    }
    /**
     * 笛卡尔坐标数组转WGS84
     * @param {Array} cartesianList 笛卡尔坐标数组
     * @returns {Array} WGS84经纬度坐标数组
     */
    static Cartesian3ListToWGS84(cartesianList) {
      let ellipsoid = Cesium.Ellipsoid.WGS84;
      let result = [];
      for (let index = 0; index < cartesianList.length; index++) {
        const cartesian = cartesianList[index];
        let cartographic = ellipsoid.cartesianToCartographic(cartesian);
        result.push({
          lng: Cesium.Math.toDegrees(cartographic.longitude),
          lat: Cesium.Math.toDegrees(cartographic.latitude),
          alt: cartographic.height,
        });
      }
      return result;
    }
   /**
     * 笛卡尔坐标数组转WGS84没有高度
     * @param {Array} cartesianList 笛卡尔坐标数组
     * @returns {Array} WGS84经纬度坐标数组
     */
    static Cartesian3ListToWGS84AltLess(cartesianList) {
      let ellipsoid = Cesium.Ellipsoid.WGS84;
      let result = [];
      for (let index = 0; index < cartesianList.length; index++) {
        const cartesian = cartesianList[index];
        let cartographic = ellipsoid.cartesianToCartographic(cartesian);
        result.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]);
      }
      return result;
    }
    /**
     * 百度坐标系转||BD-09 To GCJ-02
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static BD09ToGCJ02(lng, lat) {
      let x = +lng - 0.0065;
      let y = +lat - 0.006;
      let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * BD_FACTOR);
      let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * BD_FACTOR);
      let gg_lng = z * Math.cos(theta);
      let gg_lat = z * Math.sin(theta);
      return [gg_lng, gg_lat];
    }
   
    /**
     * GCJ-02 To BD-09
     * @param lng
     * @param lat
     * @returns {number[]}
     * @constructor
     */
    static GCJ02ToBD09(lng, lat) {
      lat = +lat;
      lng = +lng;
      let z =
        Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * BD_FACTOR);
      let theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * BD_FACTOR);
      let bd_lng = z * Math.cos(theta) + 0.0065;
      let bd_lat = z * Math.sin(theta) + 0.006;
      return [bd_lng, bd_lat];
    }
   
    /**
     * WGS-84 To GCJ-02
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static WGS84ToGCJ02(lng, lat) {
      lat = +lat;
      lng = +lng;
      if (this.out_of_china(lng, lat)) {
        return [lng, lat];
      } else {
        let d = this.delta(lng, lat);
        return [lng + d[0], lat + d[1]];
      }
    }
   
    /**
     * GCJ-02 To WGS-84
     * @param lng
     * @param lat
     * @returns {number[]}
     * @constructor
     */
    static GCJ02ToWGS84(lng, lat) {
      lat = +lat;
      lng = +lng;
      if (this.out_of_china(lng, lat)) {
        return [lng, lat];
      } else {
        let d = this.delta(lng, lat);
        let mgLng = lng + d[0];
        let mgLat = lat + d[1];
        return [lng * 2 - mgLng, lat * 2 - mgLat];
      }
    }
   
    /**
     *
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static delta(lng, lat) {
      let dLng = this.transformLng(lng - 105, lat - 35);
      let dLat = this.transformLat(lng - 105, lat - 35);
      const radLat = (lat / 180) * PI;
      let magic = Math.sin(radLat);
      magic = 1 - EE * magic * magic;
      const sqrtMagic = Math.sqrt(magic);
      dLng = (dLng * 180) / ((RADIUS / sqrtMagic) * Math.cos(radLat) * PI);
      dLat = (dLat * 180) / (((RADIUS * (1 - EE)) / (magic * sqrtMagic)) * PI);
      return [dLng, dLat];
    }
   
    /**
     *
     * @param lng
     * @param lat
     * @returns {number}
     */
    static transformLng(lng, lat) {
      lat = +lat;
      lng = +lng;
      let ret =
        300.0 +
        lng +
        2.0 * lat +
        0.1 * lng * lng +
        0.1 * lng * lat +
        0.1 * Math.sqrt(Math.abs(lng));
      ret +=
        ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
          2.0) /
        3.0;
      ret +=
        ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) /
        3.0;
      ret +=
        ((150.0 * Math.sin((lng / 12.0) * PI) +
          300.0 * Math.sin((lng / 30.0) * PI)) *
          2.0) /
        3.0;
      return ret;
    }
   
    /**
     *
     * @param lng
     * @param lat
     * @returns {number}
     */
    static transformLat(lng, lat) {
      lat = +lat;
      lng = +lng;
      let ret =
        -100.0 +
        2.0 * lng +
        3.0 * lat +
        0.2 * lat * lat +
        0.1 * lng * lat +
        0.2 * Math.sqrt(Math.abs(lng));
      ret +=
        ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
          2.0) /
        3.0;
      ret +=
        ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) /
        3.0;
      ret +=
        ((160.0 * Math.sin((lat / 12.0) * PI) +
          320 * Math.sin((lat * PI) / 30.0)) *
          2.0) /
        3.0;
      return ret;
    }
   
    /**
     *
     * @param lng
     * @param lat
     * @returns {boolean}
     */
    static out_of_china(lng, lat) {
      lat = +lat;
      lng = +lng;
      return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
    }
    static transformCartesianToWGS84(viewer, cartesian) {
      let ellipsoid = Cesium.Ellipsoid.WGS84
      let cartographic = ellipsoid.cartesianToCartographic(cartesian)
      return {
        lng: Cesium.Math.toDegrees(cartographic.longitude),
        lat: Cesium.Math.toDegrees(cartographic.latitude),
        alt: cartographic.height
      }
    }
  }
   
  export default CoordTransform;